package com.logic.modular.game.battle.panel.attribute;

import com.logic.comment.util.BeanUtil;
import com.logic.modular.game.battle.panel.attribute.domain.EffectStatus;
import com.logic.modular.game.battle.panel.attribute.domain.PlayerHeroAttribute;
import com.logic.modular.game.battle.panel.skillEffect.PvpSkillEffect;
import com.logic.modular.game.battle.panel.skillEffect.PvpSkillEffectServiceImpl;
import com.logic.modular.game.battle.panel.skillEffect.domain.SkillEffectLayer;
import com.logic.modular.game.battle.process.domain.Reason;
import com.logic.modular.game.battle.process.domain.Source;
import com.comment.pojo.domain.logic.domain.PlayerHero;
import com.logic.modular.game.player.hero.service.PlayerHeroServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import javax.annotation.Resource;


/**
 * 武将属性面板
 *
 * @author cxy
 * @since 2024-08-23 19:46:19
 */
@Slf4j
@Validated
@Service
public class PlayerHeroAttributeServiceImpl extends PlayerHeroAttributeBaseServiceImpl {
    @Resource
    private PlayerHeroServiceImpl playerHeroServiceImpl;
    @Resource
    private PvpSkillEffectServiceImpl pvpSkillEffectServiceImpl;


    public List<PlayerHeroAttribute> obtainPlayer(String battleUUID) {
        return listCache(battleUUID).stream()
                .filter(item -> item.getUid() > 0)
                .collect(Collectors.toList());
    }

    public void endRefreshTroops(String battleUUID) {
        for (PlayerHeroAttribute playerHeroAttribute : obtainPlayer(battleUUID)) {
            PlayerHero select = playerHeroServiceImpl.select(playerHeroAttribute.getUid(),playerHeroAttribute.getCoreHeroId());
            select.setId(playerHeroAttribute.getId());
            select.setCurrentForce(playerHeroAttribute.getCurrentForce());
            select.setUid(playerHeroAttribute.getUid());
            playerHeroServiceImpl.updateById(select);
        }
    }

    public double getBaseValue(String battleUUID, Long targetPlayerHeroId, String changeFieldName) {
        PlayerHeroAttribute base = getBase(battleUUID, targetPlayerHeroId);
        return BeanUtil.getTargetValue(base, changeFieldName);
    }

    public double getValue(String battleUUID, Long targetPlayerHeroId, String changeFieldName) {
        PlayerHeroAttribute base = get(battleUUID, targetPlayerHeroId);
        return BeanUtil.getTargetValue(base, changeFieldName);
    }

    public Reason statusUse(PlayerHeroAttribute attribute, long statusId) {
        Reason reason = new Reason();
        Map<Long, EffectStatus> status = attribute.getStatus();
        EffectStatus effectStatus = status.get(statusId);
        reason.setReasonSource(cn.hutool.core.bean.BeanUtil.toBean(effectStatus, Source.class));
        if (effectStatus == null) {
            reason.setSuccess(false);
            reason.setInfo("不存在效果:" + statusId);
            return reason;
        }
        reason.setSuccess(effectStatus.use());
        status.put(statusId, effectStatus);
        attribute.setStatus(status);
        return reason;
    }

    /**
     * 使用状态并刷新
     */
    public Reason statusUseAndRefresh(PlayerHeroAttribute attribute, long statusId) {
        Reason reason = statusUse(attribute, statusId);
        log.info("使用:{},结果:{}", statusId, reason);
        if (reason.isSuccess()) {
            saveCache(attribute);
        }
        return reason;
    }


    public Map<Integer, List<PlayerHeroAttribute>> obtainBothSidesSurvivalHeroMap(String battleUUID) {
        return listCache(battleUUID).stream()
                .filter(item -> item.getCurrentForce() > 0)
                .collect(Collectors.groupingBy(PlayerHeroAttribute::getRankCamp));
    }

    public List<PlayerHeroAttribute> obtainSurvivalHeroList(String battleUUID) {
        return listCache(battleUUID).stream()
                .filter(item -> item.getCurrentForce() > 0)
                .collect(Collectors.toList());
    }


    /**
     * 刷新面板
     *
     * @param pvpSkillEffect 技能效果
     */
    public void refreshPanel(PvpSkillEffect pvpSkillEffect) {
        Integer status = pvpSkillEffect.getStatus().getStatus();
        Integer isTrigger = pvpSkillEffect.status.getIsTrigger();

        switch (status) {
            case 1:
                if (isTrigger == 1) {
                    pvpSkillEffect.status.setIsTrigger(0);
                    refreshField(pvpSkillEffect);
                }
                pvpSkillEffect.status.setStatus(5);
                pvpSkillEffectServiceImpl.saveCache(pvpSkillEffect);
                break;
            case 2:
                if (isTrigger == 1) {
                    pvpSkillEffect.status.setIsTrigger(0);
                    refreshField(pvpSkillEffect);
                }
                pvpSkillEffect.status.setStatus(5);
                pvpSkillEffectServiceImpl.saveCache(pvpSkillEffect);
                break;
            case 3:
                if (isTrigger == 1) {
                    pvpSkillEffect.status.setIsTrigger(0);
                    refreshField(pvpSkillEffect);
                }
                pvpSkillEffect.status.setStatus(5);
                pvpSkillEffectServiceImpl.saveCache(pvpSkillEffect);
                break;
            case 4:
                pvpSkillEffectServiceImpl.remove(pvpSkillEffect);
                refreshField(pvpSkillEffect);
                break;
            case 5:
                pvpSkillEffect.status.setStatus(5);
                pvpSkillEffectServiceImpl.saveCache(pvpSkillEffect);
                break;
            default:
                break;
        }

    }

    public void refreshField(PvpSkillEffect skillEffect) {
        String battleUUID = skillEffect.getBattleUUID();
        Long coreSkillEffectTypeId = skillEffect.getCoreSkillEffectTypeId();
        Long targetPlayerHeroId = skillEffect.getTargetPlayerHeroId();
        Long sourcePlayerHeroId = skillEffect.getSourcePlayerHeroId();
        SkillEffectLayer skillEffectLayer = skillEffect.getSkillEffectLayer();
        String name = skillEffectLayer.getName();
        Double thisChangeValue = skillEffectLayer.getThisChangeValue();

        PlayerHeroAttribute sourceAttribute = selectCache(battleUUID, sourcePlayerHeroId);
        sourceAttribute.attributeUpdate(
                name, thisChangeValue,
                1, 1,
                coreSkillEffectTypeId
        );
        PlayerHeroAttribute targetAttribute = selectCache(battleUUID, targetPlayerHeroId);
        skillEffectLayer.setTargetPlayerHeroId(targetAttribute.getId());

        skillEffectLayer.setLastEndValue(
                targetAttribute.attributeUpdate(name, thisChangeValue, 0, 1, coreSkillEffectTypeId)
        );
        skillEffect.setSkillEffectLayer(skillEffectLayer);
        saveCache(sourceAttribute);
        saveCache(targetAttribute);
    }

    public Set<Long> getDeathLabel(String battleUUID) {
        return listCache(battleUUID).stream()
                .filter(item -> item.getCurrentForce() <= 0)
                .mapToLong(PlayerHeroAttribute::getId)
                .boxed()
                .collect(Collectors.toSet());
    }

    /**
     * 初始化战斗面板
     *
     * @param uuid        战斗编号
     * @param battleCount 战斗场次
     * @return 面板列表
     */
    public List<PlayerHeroAttribute> initBattlePanel(String uuid, int battleCount) {
        Map<Object, Object> map = redisUtils.hGetAll(String.format(PlayerHeroAttribute_key, uuid));
        Map<Object, Object> baseMap = redisUtils.hGetAll(String.format(PlayerHeroAttribute_base_key, uuid));
        map.forEach((k, v) -> {
            PlayerHeroAttribute playerHeroAttribute = (PlayerHeroAttribute) v;
            PlayerHeroAttribute back = (PlayerHeroAttribute) baseMap.get(k);
            back.setCurrentForce(playerHeroAttribute.getCurrentForce());
            back.setBattleCount(battleCount);
            map.put(k, back);
        });
        redisUtils.hPutAll(String.format(PlayerHeroAttribute_key, uuid), map, 20, TimeUnit.MINUTES);
        return map.values().stream().map(item -> (PlayerHeroAttribute) item).collect(Collectors.toList());
    }
}
